using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Athena.Core
{
    [Serializable()]
    public class Species : Node
    {
        public static int COUNT = 0;

        public override void GenerateDrawable(System.Drawing.PointF point)
        {
            _Drawable = new Objects.SpeciesGlyph(point);
            _Drawable.Item = this;
        }

        public override object Clone()
        {
            if (this == Module.Empty) return null;
            Species result = new Species(ItemType, ID, Concentration);
            result._Boundary = _Boundary;
            return result;
        }

        protected double _Concentration = 0;
        public virtual double Concentration
        {
            get { return _Concentration; }
            set { _Concentration = value; }
        }

        protected bool _Boundary = false;
        public virtual bool Boundary
        {
            get { return _Boundary; }
            set { _Boundary = value; }
        }

        public virtual bool GetBoundary(Module module)
        {
            Module parent = ParentModule;
            if (module != null && parent != null && module.IsParentOf(parent))
            {
                Item i = parent.GetMappingTo(this);
                if (i is Node && i != this)
                    return false;

                i = parent.GetMappingFrom(this);
                if (i is Node && i != this)
                    return false;
            }
            return _Boundary;
        }

        public Species() : base("species","species")
        {
            Concentration = 0;
            Boundary = false;
            ++COUNT;
        }
        public Species(string type, string name, double concentration) : base(type, name) 
        { 
            Concentration = concentration;
            Boundary = false;
            ++COUNT;
        }
        public Species(string type, string name, bool boundary, double concentration)
            : base(type, name)
        {
            Concentration = concentration;
            Boundary = boundary;
            ++COUNT;
        }

        public override void Mirror(Item other)
        {
            if (other is Species)
            {
                Species copy = (Species)other;
                ItemType = copy.ItemType;
                Concentration = copy.Concentration;
                Boundary = copy.Boundary;
            }
        }

        /// <summary>
        /// destructor. calls Remove()
        /// </summary>
        ~Species()
        {
            Remove();
        }

        /// <summary>
        /// Writes the XML for this class
        /// </summary>
        /// <param name="writer">xml writer</param>
        public override void WriteXML(XmlWriter writer)
        {
            base.WriteXML(writer);

            writer.WriteStartElement("Species", "");

            writer.WriteStartElement("Boundary", "");
            writer.WriteValue(Boundary);
            writer.WriteEndElement();

            writer.WriteStartElement("Concentration", "");
            writer.WriteValue(Concentration);
            writer.WriteEndElement();
            
            writer.WriteEndElement();
        }

        /// <summary>
        /// Reads the information from an XML file
        /// </summary>
        /// <param name="reader">xlm reader</param>
        public override bool ReadXML(XmlReader reader)
        {
            bool read = base.ReadXML(reader);
            if (!read) return false;

            if (!(reader.NodeType == XmlNodeType.Element && reader.Name == "Species"))
                read = reader.Read();
            
            if (reader.NodeType == XmlNodeType.Element && reader.Name == "Species")
            {
                read = reader.Read();
                while (read)
                {
                    if (reader.NodeType == XmlNodeType.EndElement)
                        break;
                    
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.Name)
                        {
                            case "Boundary":
                                read = reader.Read();
                                if (reader.NodeType == XmlNodeType.Text)
                                    Boundary = reader.ReadContentAsBoolean();
                                break;
                            case "Concentration":
                                read = reader.Read();
                                if (reader.NodeType == XmlNodeType.Text)
                                    Concentration = reader.ReadContentAsDouble();
                                break;
                            default:
                                while (reader.NodeType != XmlNodeType.EndElement)
                                    read = reader.Read();
                                break;
                        }
                    }

                    if (!read || (reader.NodeType == XmlNodeType.EndElement && reader.Name == "Species")) break;

                    if (reader.NodeType != XmlNodeType.Element)
                        read = reader.Read();
                }
                return true;
            }
            return false;
        }
    }
}
